package com.winchain.chainbill.bill.base.service.impl;

import com.shell.bee.base.utils.StringUtil;
import com.shell.bee.base.utils.SystemUtil;
import com.shell.bee.persistence.service.impl.PersistentServiceImpl;
import com.shell.framework.utils.SysDateUtil;
import com.winchain.chainbill.bill.base.dao.CbDctDao;
import com.winchain.chainbill.bill.base.dao.CbInsAcrDao;
import com.winchain.chainbill.bill.base.dao.CbRecDao;
import com.winchain.chainbill.bill.base.po.CbDct;
import com.winchain.chainbill.bill.base.po.CbInsAcr;
import com.winchain.chainbill.bill.base.po.CbRec;
import com.winchain.chainbill.bill.base.service.CbDctService;
import com.winchain.chainbill.bill.biz.discount.vo.BillDct;
import com.winchain.chainbill.bill.biz.query.vo.CbDctOverdueVo;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service("cbDctService")
public class CbDctServiceImpl extends PersistentServiceImpl<CbDct> implements CbDctService {
	@Autowired
	private CbRecDao cbRecDao;
	@Autowired
	private CbDctDao cbDctDao;
	@Autowired
	private CbInsAcrDao cbInsAcrDao;

	public List<BillDct> selectBillDctsByBillIdAndState(String billId, String dctState) {
		List<BillDct> bills = this.cbDctDao.selectBillDctsByPrntIdAndBillState(billId, "S000");
		if ((bills == null) || (bills.isEmpty())) {
			bills = this.cbDctDao.selectBillDctsByBillIdAndState(billId, dctState);
			if ((bills != null) && (bills.size() > 0)) {
				((BillDct) bills.get(0)).setDctPrntId(billId);
			}
		} else {
			CbRec cbRec = (CbRec) this.cbRecDao.selectByPrimaryKey(billId);
			BillDct billDct = new BillDct();
			billDct.setBillId(cbRec.getBillId());
			billDct.setBillCode(cbRec.getBillCode());
			billDct.setCbOptSeq(cbRec.getOptSeq());
			billDct.setBillType(cbRec.getBillType());
			billDct.setRootId(cbRec.getRootId());
			billDct.setPrntId(cbRec.getPrntId());
			billDct.setBillAmt(cbRec.getBillAmt());
			billDct.setHldrLvl(cbRec.getHldrLvl());
			billDct.setSndDate(cbRec.getSndDate());
			billDct.setBillState(cbRec.getBillState());
			billDct.setExpDate(cbRec.getExpDate());
			bills.add(billDct);
		}
		return bills;
	}

	public BillDct selectBillDctByBillIdAndState(String billId, String DctState) {
		return this.cbDctDao.selectBillDctByBillIdAndState(billId, DctState);
	}

	public int saveBillDctsByDctDate(CbDct cbDct, BigDecimal rpurInt, boolean isRpur) {
		int result = 0;
		try {
			String dctDate = cbDct.getPmtDate();
			if (StringUtil.emptyAndNull(dctDate)) {
				dctDate = cbDct.getDctDate();
			}
			BigDecimal dctInt = cbDct.getDctInt();
			if (cbDct.getDeductInt() != null) {
				dctInt = dctInt.subtract(cbDct.getDeductInt());
			}
			if (dctInt.compareTo(BigDecimal.ZERO) == 0) {
				return 1;
			}
			BigDecimal dctDays = new BigDecimal(SysDateUtil.getDaysBetween(dctDate, cbDct.getExpDate()));
			List<String> monthList = SysDateUtil.getMonthBetween(dctDate, cbDct.getExpDate());
			BigDecimal earlyIns = new BigDecimal(0);
			for (int i = 0; i < monthList.size(); i++) {
				String month = (String) monthList.get(i);
				CbInsAcr cbInsAcr = new CbInsAcr();
				cbInsAcr.setAcrId(SystemUtil.getUUID());
				cbInsAcr.setBizId(cbDct.getDctId());
				cbInsAcr.setAcrMonth(SysDateUtil.parseDate(month, "yyyy-MM", "yyyyMM"));
				cbInsAcr.setAcrInsType("1");
				cbInsAcr.setCreateTime(SysDateUtil.getSystemDateTime());
				String mdMonth = SysDateUtil.parseDate(month, "yyyy-MM", "yyyyMMdd");
				String firstDate = SysDateUtil.getDateOffsetWithDayType(mdMonth, 0, -1);
				String lastDate = SysDateUtil.getDateOffsetWithDayType(mdMonth, 0, 1);

				int monthLen = monthList.size();
				if (monthLen == 1) {
					firstDate = dctDate;
					lastDate = cbDct.getExpDate();
				} else if (i == 0) {
					firstDate = dctDate;
				} else if (i == monthList.size() - 1) {
					lastDate = cbDct.getExpDate();
				}
				cbInsAcr.setStartDate(firstDate);
				cbInsAcr.setEndDate(lastDate);
				int betweenDays = SysDateUtil.getDaysBetween(firstDate, lastDate) + 1;
				BigDecimal betweenDaysBig = new BigDecimal(betweenDays);

				BigDecimal totalDaysAmt = BigDecimal.ZERO;
				BigDecimal curIns;
				if ((monthLen == 1) || (i == 0)) {
					betweenDays -= 1;
					betweenDaysBig = new BigDecimal(betweenDays);
					if ((monthLen == 1) && (isRpur)) {
						curIns = dctInt.subtract(rpurInt);
					} else {
						if ((i == 0) && (monthLen > 1)) {
							curIns = dctInt.multiply(betweenDaysBig.add(BigDecimal.ONE)).divide(dctDays, 2, 5);
						} else {
							curIns = dctInt.subtract(earlyIns);
						}
					}
					if ((firstDate.equals(lastDate)) && (isRpur)) {
						totalDaysAmt = cbDct.getDctAmt().multiply(betweenDaysBig.add(BigDecimal.ONE));
					} else if ((i == 0) && (monthLen > 1)) {
						totalDaysAmt = cbDct.getDctAmt().multiply(betweenDaysBig.add(BigDecimal.ONE));
					} else {
						totalDaysAmt = cbDct.getDctAmt().multiply(betweenDaysBig);
					}
				} else if (i == monthList.size() - 1) {
					if (isRpur) {
						curIns = dctInt.subtract(earlyIns).subtract(rpurInt);
					} else {
						curIns = dctInt.subtract(earlyIns);
					}
					totalDaysAmt = cbDct.getDctAmt().multiply(betweenDaysBig.subtract(BigDecimal.ONE));
				} else {
					curIns = dctInt.multiply(betweenDaysBig).divide(dctDays, 2, 5);
					totalDaysAmt = cbDct.getDctAmt().multiply(betweenDaysBig);
				}
				cbInsAcr.setCurIns(curIns);

				cbInsAcr.setEarlyIns(earlyIns);

				BigDecimal totIns = curIns.add(earlyIns);
				cbInsAcr.setTotIns(totIns);

				earlyIns = earlyIns.add(curIns);

				cbInsAcr.setTotDaysAmt(totalDaysAmt);
				result = this.cbInsAcrDao.insert(cbInsAcr);
			}
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return result;
	}

	public CbDct selectDctByBillIdAndStates(String billId, List<String> dctStates) {
		return this.cbDctDao.selectDctByBillIdAndStates(billId, dctStates);
	}

	public BigDecimal sumDctPaidAmt(String cusId, String issuer, String strtDate, String... grpIds) {
		return this.cbDctDao.sumDctPaidAmt(cusId, issuer, strtDate, grpIds);
	}

	public List<CbDctOverdueVo> selectDctOverdueRecord(String currentDate) {
		return this.cbDctDao.selectDctOverdueRecord(currentDate);
	}
}
